#include "student.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <ctime>
#include <sstream>
#include <cstring>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <thread>
#include <mutex>
#include <iomanip>

using namespace std;

mutex mtx; // 用于保护对学生数据的访问
vector<student> students; // 存储学生信息的向量
const int MAX_STUDENTS = 1000; // 存储的最大学生数量

// 获取当前日期和时间作为文件名
string current_datetime() {
    time_t now = time(nullptr);
    char buffer[80];
    strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", localtime(&now));
    return buffer;
}

// 将学生数据写入文件
void write_to_file(const vector<student>& students, const string& filename) {
    ofstream file(filename);
    if (!file.is_open()) {
        cerr << "无法打开文件: " << filename << endl;
        return;
    }
    
    for (const auto& s : students) {
        file << s.name << "," << s.number << "," << s.grade << "," << s.hobby[0] << "," << s.hobby[1] << "," << s.hobby[2] << "\n";
    }
    file.close();
    cout << "数据已写入文件: " << filename << endl;
}

// 处理客户端连接
void handle_connection(int client_sock) {
    try {
        while (true) {
            char data[1024]; // 用于接收客户端数据的缓冲区
            int bytes_read = read(client_sock, data, sizeof(data)); // 读取数据
            if (bytes_read <= 0) {
                // 如果没有读取到数据，可能是连接断开，写入数据并退出循环
                unique_lock<mutex> lock(mtx);
                if (!students.empty()) {
                    string filename = "../" + current_datetime() + ".txt"; // 保存文件到上一级目录
                    write_to_file(students, filename);
                    students.clear(); // 清空学生数据向量
                }
                break;
            }

            // 解析接收到的数据
            istringstream ss(string(data, bytes_read));
            string name, number, grade, hobby1, hobby2, hobby3;
            getline(ss, name, ',');
            getline(ss, number, ',');
            getline(ss, grade, ',');
            getline(ss, hobby1, ',');
            getline(ss, hobby2, ',');
            getline(ss, hobby3, '\n');

            student s;
            s.name = name;
            s.number = stol(number); // 将字符串转换为长整型
            s.grade = stol(grade); // 将字符串转换为长整型
            s.hobby = {hobby1, hobby2, hobby3};

            // 保护对学生数据向量的访问
            unique_lock<mutex> lock(mtx);
            students.push_back(s);
            if (students.size() >= MAX_STUDENTS) {
                // 如果学生数量达到上限，进行排序并写入文件
                sort(students.begin(), students.end(), [](const student& a, const student& b) {
                    if (a.number != b.number)
                        return a.number < b.number;
                    else
                        return a.grade < b.grade;
                });
                string filename = "../" + current_datetime() + ".txt"; // 保存文件到上一级目录
                write_to_file(students, filename);
                students.clear(); // 清空学生数据向量
            }
        }
    } catch (exception& e) {
        cerr << "线程中发生异常: " << e.what() << "\n"; // 捕获并报告异常
    }
    close(client_sock); // 关闭客户端套接字
}

void start_server(short port) {
    int server_fd;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    
    // 创建套接字
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        cerr << "创建套接字失败" << endl;
        exit(EXIT_FAILURE);
    }
    
    // 设置套接字选项
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        cerr << "设置套接字选项失败" << endl;
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 设置地址和端口
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(port);
    
    // 绑定套接字
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        cerr << "绑定套接字失败" << endl;
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    // 监听连接
    if (listen(server_fd, 3) < 0) {
        cerr << "监听套接字失败" << endl;
        close(server_fd);
        exit(EXIT_FAILURE);
    }
    
    while (true) {
        int client_sock;
        // 接受连接
        if ((client_sock = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
            cerr << "接受连接失败" << endl;
            close(server_fd);
            exit(EXIT_FAILURE);
        }
        // 创建一个新线程来处理连接
        thread(handle_connection, client_sock).detach();
    }
}

int main() {
    // 启动两个服务器线程
    thread t1(start_server, 12345);
    thread t2(start_server, 12346);
    t1.join();
    t2.join();
    return 0;
}
